package cn.aspart.security.handler;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.*;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Component
public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler {

    private static final Map<String, Integer> LOGIN_ATTEMPTS = new ConcurrentHashMap<>();
    private static final int MAX_ATTEMPTS = 3;


    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        String username = request.getParameter("username");
        log.info("username {} login fail", username);

        String errorMsg = "";
        if (!StringUtils.hasText(username)) {
            errorMsg = "用户名/密码不能为空";
            sendRedirect(request, response, username, errorMsg);
            return;
        } else {
            LOGIN_ATTEMPTS.put(username, LOGIN_ATTEMPTS.getOrDefault(username, 0) + 1);
            if (LOGIN_ATTEMPTS.get(username) >= MAX_ATTEMPTS) {
                errorMsg = "由于多次登录失败，账户已被锁定";
            }
        }

        if (!StringUtils.hasText(errorMsg)) {
            errorMsg = getErrorMessage(exception);
        }

//        request.getSession().setAttribute("errorMessageage", errorMsg);
//        response.sendRedirect(request.getContextPath() + "/login?error");
        sendRedirect(request, response, username, errorMsg);

    }

    private void sendRedirect(HttpServletRequest request, HttpServletResponse response, String username,
                              String errorMessage) throws IOException {
        // 将错误信息和剩余尝试次数存储到session中
        HttpSession session = request.getSession();
        session.setAttribute("errorMessage", errorMessage);
        if (StringUtils.hasText(username) && LOGIN_ATTEMPTS.containsKey(username)) {
            session.setAttribute("remainingAttempts", MAX_ATTEMPTS - LOGIN_ATTEMPTS.get(username));
        }

        // 重定向到登录页面
        response.sendRedirect(request.getContextPath() + "/login?error");
    }

    // 根据不同的异常类型返回不同的错误信息
    private String getErrorMessage(AuthenticationException exception) {
        if (exception instanceof BadCredentialsException) {
            return "用户名或密码错误";
        } else if (exception instanceof LockedException) {
            return "账户已被锁定，请联系管理员";
        } else if (exception instanceof DisabledException) {
            return "账户已被禁用，请联系管理员";
        } else if (exception instanceof AccountExpiredException) {
            return "账户已过期，请联系管理员";
        } else if (exception instanceof CredentialsExpiredException) {
            return "密码已过期，请重置密码";
        } else {
            return "登录失败，请稍后再试";
        }
    }

    public static void resetAttempts(String username) {
        if (StringUtils.hasText(username)) {
            LOGIN_ATTEMPTS.remove(username);
        }
    }
}
